home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -in_the_mag- / emulation / macos / uae069b2.src.cpt.hqx / UAE069ß2.SRC.CPT / uae069fl2.src / gfxlib.c < prev    next >
C/C++ Source or Header  |  1997-06-27  |  47KB  |  1,657 lines

  1.  /*
  2.   * UAE - The Un*x Amiga Emulator
  3.   *
  4.   * graphics.library emulation
  5.   *
  6.   * Copyright 1996, 1997 Bernd Schmidt
  7.   * 
  8.   * Ideas for this:
  9.   * Rewrite layers completely. When there are lots of windows on the screen
  10.   * it can take 3 minutes to update everything after resizing or moving one
  11.   * (at least with Kick 1.3). Hide the internal structure of the layers as far
  12.   * as possible, keep most of the data in emulator space so we save copying/
  13.   * conversion time. Programs really shouldn't do anything directly with the
  14.   * Layer or ClipRect structures.
  15.   * This means that a lot of graphics.library functions will have to be
  16.   * rewritten as well.
  17.   * Once that's done, add support for non-planar bitmaps. Conveniently, the
  18.   * struct Bitmap has an unused pad field which we could abuse as some sort of
  19.   * type field. Need to add chunky<->planar conversion routines to get it
  20.   * going, plus variants of all the drawing functions for speed reasons.
  21.   * 
  22.   * When it becomes necessary to convert a structure from Amiga memory, make
  23.   * a function with a name ending in ..FA, which takes a pointer to the
  24.   * native structure and a uaecptr and returns the native pointer.
  25.   */
  26.  
  27. #include "sysconfig.h"
  28. #include "sysdeps.h"
  29.  
  30. #include <assert.h>
  31.  
  32. #include "config.h"
  33. #include "options.h"
  34. #include "my_memory.h"
  35. #include "custom.h"
  36. #include "readcpu.h"
  37. #include "newcpu.h"
  38. #include "xwin.h"
  39. #include "autoconf.h"
  40. #include "osemu.h"
  41. #include "osdep/exectasks.h"
  42.  
  43. #ifdef USE_EXECLIB
  44.  
  45. /* Uniq list management. Should be in a separate file. */
  46. struct uniq_head {
  47.     struct uniq_head *next;
  48.     uae_u32 uniq;
  49. };
  50.  
  51. typedef struct {
  52.     struct uniq_head *head;
  53.     uae_u32 uniq;
  54. } uniq_list;
  55.  
  56. #define UNIQ_INIT { NULL, 1 }
  57.  
  58. static void init_uniq(uniq_list *list)
  59. {
  60.     list->head = NULL;
  61.     list->uniq = 1;
  62. }
  63.  
  64. static struct uniq_head *find_uniq (uniq_list *a, uae_u32 uniq)
  65. {
  66.     struct uniq_head *b = a->head;
  67.     while (b && b->uniq != uniq)
  68.     b = b->next;
  69.     if (!b)
  70.     write_log("Couldn't find structure. Bad\n");
  71.     return b;
  72. }
  73.  
  74. static struct uniq_head *find_and_rem_uniq (uniq_list *a, uae_u32 uniq)
  75. {
  76.     struct uniq_head **b = &a->head, *c;
  77.     while (*b && (*b)->uniq != uniq)
  78.     b = &(*b)->next;
  79.     c = *b;
  80.     if (!c)
  81.     write_log("Couldn't find structure. Bad\n");
  82.     else
  83.     *b = c->next;
  84.     return c;
  85. }
  86.  
  87. static void add_uniq (uniq_list *a, struct uniq_head *item, uaecptr amem)
  88. {
  89.     item->uniq = a->uniq++;
  90.     put_long(amem, item->uniq);
  91.     if (a->uniq == 0)
  92.     a->uniq++;
  93.     item->next = a->head;
  94.     a->head = item;
  95. }
  96.  
  97. /* Graphics stuff begins here */
  98. #define CLIPRECT_SIZE 40
  99. #define LAYER_SIZE 160
  100. #define LINFO_SIZE 102
  101.  
  102. static uaecptr gfxbase, layersbase;
  103.  
  104. static void do_LockLayer(uaecptr layer)
  105. {
  106. #if 0 /* Later.. */
  107.     uaecptr sigsem = layer + 72;
  108.     m68k_areg(regs, 0) = sigsem;
  109.     CallLib(get_long(4), -564);
  110. #else
  111.     m68k_areg(regs, 1) = layer;
  112.     CallLib(layersbase, -96);
  113. #endif
  114. }
  115.  
  116. static void do_UnlockLayer(uaecptr layer)
  117. {
  118.     m68k_areg(regs, 0) = layer;
  119.     CallLib(layersbase, -102);
  120. }
  121.  
  122. static uae_u32 gfxlibname, layerslibname;
  123.  
  124. struct Rectangle {
  125.     int MinX, MinY, MaxX, MaxY;
  126. };
  127.  
  128. static int GFX_PointInRectangle(uaecptr rect, int x, int y)
  129. {
  130.     uae_s16 minx = get_word(rect);
  131.     uae_s16 miny = get_word(rect+2);
  132.     uae_s16 maxx = get_word(rect+4);
  133.     uae_s16 maxy = get_word(rect+6);
  134.     
  135.     if (x < minx || x > maxx || y < miny || y > maxy)
  136.     return 0;
  137.     return 1;
  138. }
  139.  
  140. static int GFX_RectContainsRect(struct Rectangle *r1, struct Rectangle *r2)
  141. {
  142.     return (r2->MinX >= r1->MinX && r2->MaxX <= r1->MaxX
  143.         && r2->MinY >= r1->MinY && r2->MaxY <= r1->MaxY);
  144. }
  145.  
  146. static struct Rectangle *GFX_RectFA(struct Rectangle *rp, uaecptr rect)
  147. {
  148.     rp->MinX = (uae_s16)get_word(rect);
  149.     rp->MinY = (uae_s16)get_word(rect+2);
  150.     rp->MaxX = (uae_s16)get_word(rect+4);
  151.     rp->MaxY = (uae_s16)get_word(rect+6);
  152.     return rp;
  153. }
  154.  
  155. static int GFX_Bitmap_WritePixel(uaecptr bitmap, int x, int y, uaecptr rp)
  156. {
  157.     int i, offs;
  158.     unsigned int bpr = get_word (bitmap);
  159.     unsigned int rows = get_word (bitmap + 2);
  160.     uae_u16 mask;
  161.  
  162.     uae_u8 planemask = get_byte(rp + 24);
  163.     uae_u8 fgpen = get_byte(rp + 25);
  164.     uae_u8 bgpen = get_byte(rp + 26);
  165.     uae_u8 drmd = get_byte(rp + 28);
  166.     uae_u8 pen = drmd & 4 ? bgpen : fgpen;
  167.  
  168.     if (x < 0 || y < 0 || x >= 8*bpr || y >= rows)
  169.     return -1;
  170.     
  171.     offs = y*bpr + (x & ~15)/8;
  172.  
  173.     for (i = 0; i < get_byte (bitmap + 5); i++) {
  174.     uaecptr planeptr;
  175.     uae_u16 data;
  176.  
  177.     if ((planemask & (1 << i)) == 0)
  178.         continue;
  179.  
  180.     planeptr = get_long(bitmap + 8 + i*4);
  181.     data = get_word(planeptr + offs);
  182.     
  183.     mask = 0x8000 >> (x & 15);
  184.     
  185.     if (drmd & 2) {
  186.         if ((pen & (1 << i)) != 0)
  187.         data ^=mask;
  188.     } else {
  189.         data &= ~mask;
  190.         if ((pen & (1 << i)) != 0)
  191.         data |= mask;
  192.      }
  193.     put_word(planeptr + offs, data);
  194.     }
  195.     return 0;
  196. }
  197.  
  198. int GFX_WritePixel(uaecptr rp, int x, int y)
  199. {
  200.     int v;
  201.     uaecptr layer = get_long(rp);
  202.     uaecptr bitmap = get_long(rp + 4);
  203.     uaecptr cliprect;
  204.     int x2, y2;
  205.  
  206.     if (bitmap == 0) {
  207.     fprintf(stderr, "bogus RastPort in WritePixel\n");
  208.     return -1;
  209.     }
  210.  
  211.     /* Easy case first */
  212.     if (layer == 0) {
  213.     return GFX_Bitmap_WritePixel(bitmap, x, y, rp);
  214.     }
  215.     do_LockLayer(layer);
  216.     /*
  217.      * Now, in theory we ought to obtain the semaphore.
  218.      * Since we don't, the programs will happily write into the raster
  219.      * even though we are currently moving the window around.
  220.      * Not good.
  221.      */
  222.     
  223.     x2 = x + (uae_s16)get_word(layer + 16);
  224.     y2 = y + (uae_s16)get_word(layer + 18);
  225.  
  226.     if (!GFX_PointInRectangle (layer + 16, x2, y2)) {
  227.     do_UnlockLayer(layer);
  228.     return -1;
  229.     }
  230.     /* Find the right ClipRect */
  231.     cliprect = get_long(layer + 8);
  232.     while (cliprect != 0 && !GFX_PointInRectangle (cliprect + 16, x2, y2))
  233.     cliprect = get_long(cliprect);
  234.     if (cliprect == 0) {
  235.     /* Don't complain: The "Dots" demo does this all the time. I
  236.      * suppose if we can't find a ClipRect, we aren't supposed to draw
  237.      * the dot.
  238.      */
  239.     /*fprintf(stderr, "Weirdness in WritePixel\n");*/
  240.     v = -1;
  241.     } else if (get_long(cliprect + 8) == 0) {
  242.     v = GFX_Bitmap_WritePixel(bitmap, x2, y2, rp);
  243.     } else if (get_long(cliprect + 12) == 0) {
  244.     /* I don't really know what to do here... */
  245.     v = 0;
  246.     } else {
  247.     /* This appears to be normal for smart refresh layers which are obscured */
  248.     v = GFX_Bitmap_WritePixel (get_long(cliprect + 12), x2 - (uae_s16)get_word(cliprect + 16), 
  249.                    y2 - (uae_s16)get_word(cliprect + 18), rp);
  250.     }
  251.     do_UnlockLayer(layer);
  252.     return v;
  253. }
  254.  
  255.  
  256. static uae_u32 gfxl_WritePixel(void) { return GFX_WritePixel(m68k_areg(regs, 1), (uae_s16)m68k_dreg(regs, 0), (uae_s16)m68k_dreg(regs, 1)); }
  257.  
  258. static uae_u32 gfxl_BltClear(void)
  259. {
  260.     uaecptr mem=m68k_areg(regs, 1);
  261.     uae_u8 *mptr = chipmem_bank.xlateaddr(m68k_areg(regs, 1));
  262.     uae_u32 count=m68k_dreg(regs, 0);
  263.     uae_u32 flags=m68k_dreg(regs, 1);
  264.     unsigned int i;
  265.     uae_u32 pattern;
  266.  
  267.     if ((flags & 2) == 2){
  268.     /* count is given in Rows / Bytes per row */
  269.     count=(count & 0xFFFF) * (count >> 16);
  270.     }
  271.  
  272.     if ((mem & 1) != 0 || (count & 1) != 0)
  273.     fprintf(stderr, "gfx: BltClear called with odd parameters\n");
  274.     
  275.     /* Bit 2 set means use pattern (V36+ only, but we might as well emulate
  276.      * it always) */
  277.     if ((flags & 4) == 0)
  278.     pattern = 0;
  279.     else
  280.     pattern= ((flags >> 16) & 0xFFFF) | (flags & 0xFFFF0000ul);
  281.  
  282.     if ((pattern & 0xFF) == ((pattern >> 8) & 0xFF)) {
  283.     memset(mptr, pattern, count);
  284.     return 0;
  285.     }
  286.  
  287.     for(i = 0; i < count; i += 4) 
  288.     chipmem_bank.lput(mem+i, pattern);
  289.     
  290.     if ((count & 3) != 0)
  291.     chipmem_bank.wput(mem + i - 4, pattern);
  292.  
  293.     return 0;
  294. }  
  295.  
  296. static uae_u32 gfxl_BltBitmap(void)
  297. {
  298.     uaecptr srcbitmap = m68k_areg(regs, 0), dstbitmap = m68k_areg(regs, 1);
  299.     int srcx = (uae_s16)m68k_dreg(regs, 0), srcy = (uae_s16)m68k_dreg(regs, 1);
  300.     int dstx = (uae_s16)m68k_dreg(regs, 2), dsty = (uae_s16)m68k_dreg(regs, 3);
  301.     int sizex = (uae_s16)m68k_dreg(regs, 4), sizey = (uae_s16)m68k_dreg(regs, 5);
  302.     uae_u8 minterm = (uae_u8)m68k_dreg(regs, 6), mask = m68k_dreg(regs, 7);
  303.     return 0; /* sam: a return was missing here ! */   
  304. }
  305.  
  306. static uaecptr amiga_malloc(int len)
  307. {
  308.     m68k_dreg(regs, 0) = len;
  309.     m68k_dreg(regs, 1) = 1; /* MEMF_PUBLIC */
  310.     return CallLib(get_long(4), -198); /* AllocMem */
  311. }
  312.  
  313. static void amiga_free(uaecptr addr, int len)
  314. {
  315.     m68k_areg(regs, 1) = addr;
  316.     m68k_dreg(regs, 0) = len;
  317.     CallLib(get_long(4), -210); /* FreeMem */
  318. }
  319.  
  320. /*
  321.  * Region handling code
  322.  * 
  323.  * General ideas stolen from xc/verylongpath/miregion.c
  324.  *
  325.  * The Clear code is untested. And and Or seem to work, Xor is only used
  326.  * by the 1.3 Prefs program and seems to work, too.
  327.  */
  328.  
  329. struct RegionRectangle {
  330.     struct RegionRectangle *Next,*Prev;
  331.     struct Rectangle bounds;
  332. };
  333.  
  334. struct My_Region {
  335.     struct Rectangle bounds;
  336.     struct RegionRectangle *RegionRectangle;
  337. };
  338.  
  339. struct RectList {
  340.     int count;
  341.     int space;
  342.     struct Rectangle bounds;
  343.     struct Rectangle *rects;
  344. };
  345.  
  346. struct BandList {
  347.     int count;
  348.     int space;
  349.     int *miny, *maxy;
  350. };
  351.  
  352. static void init_bandlist(struct BandList *bl)
  353. {
  354.     bl->count = 0;
  355.     bl->space = 20;
  356.     bl->miny = (int *)malloc(20*sizeof(int));
  357.     bl->maxy = (int *)malloc(20*sizeof(int));
  358. }
  359.  
  360. static void dup_bandlist(struct BandList *to, struct BandList *from)
  361. {
  362.     to->count = from->count;
  363.     to->space = to->count+4;
  364.     to->miny = (int *)malloc (to->space*sizeof(int));
  365.     to->maxy = (int *)malloc (to->space*sizeof(int));
  366.     memcpy(to->miny, from->miny, to->count*sizeof(int));
  367.     memcpy(to->maxy, from->maxy, to->count*sizeof(int));
  368. }
  369.  
  370. static __inline__ void add_band(struct BandList *bl, int miny, int maxy, int pos)
  371. {
  372.     if (bl->count == bl->space) {
  373.     bl->space += 20;
  374.     bl->miny = (int *)realloc(bl->miny, bl->space*sizeof(int));    
  375.     bl->maxy = (int *)realloc(bl->maxy, bl->space*sizeof(int));    
  376.     }
  377.     memmove(bl->miny + pos + 1, bl->miny + pos, (bl->count - pos) * sizeof(int));
  378.     memmove(bl->maxy + pos + 1, bl->maxy + pos, (bl->count - pos) * sizeof(int));
  379.     bl->count++;
  380.     bl->miny[pos] = miny;
  381.     bl->maxy[pos] = maxy;
  382. }
  383.  
  384. static void init_rectlist(struct RectList *rl)
  385. {
  386.     rl->count = 0;
  387.     rl->space = 100;
  388.     rl->bounds.MinX = rl->bounds.MinY = rl->bounds.MaxX = rl->bounds.MaxY = 0;
  389.     rl->rects = (struct Rectangle *)malloc(100*sizeof(struct Rectangle));
  390. }
  391.  
  392. static void dup_rectlist(struct RectList *to, struct RectList *from)
  393. {
  394.     to->count = from->count;
  395.     to->space = to->count+4;
  396.     to->bounds = from->bounds;
  397.     to->rects = (struct Rectangle *)malloc (to->space*sizeof(struct Rectangle));
  398.     memcpy(to->rects, from->rects, to->count*sizeof(struct Rectangle));
  399. }
  400.  
  401. static __inline__ void add_rect(struct RectList *rl, struct Rectangle r)
  402. {
  403.     if (rl->count == 0)
  404.     rl->bounds = r;
  405.     else {
  406.     if (r.MinX < rl->bounds.MinX)
  407.         rl->bounds.MinX = r.MinX;
  408.     if (r.MinY < rl->bounds.MinY)
  409.         rl->bounds.MinY = r.MinY;
  410.     if (r.MaxX > rl->bounds.MaxX)
  411.         rl->bounds.MaxX = r.MaxX;
  412.     if (r.MaxY > rl->bounds.MaxY)
  413.         rl->bounds.MaxY = r.MaxY;
  414.     }
  415.     if (rl->count == rl->space) {
  416.     rl->space += 100;
  417.     rl->rects = (struct Rectangle *)realloc(rl->rects, rl->space*sizeof(struct Rectangle));    
  418.     }
  419.     rl->rects[rl->count++] = r;
  420. }
  421.  
  422. static __inline__ void rem_rect(struct RectList *rl, int num)
  423. {
  424.     rl->count--;
  425.     if (num == rl->count)
  426.     return;
  427.     rl->rects[num] = rl->rects[rl->count];
  428. }
  429.  
  430. static void free_rectlist(struct RectList *rl)
  431. {
  432.     free(rl->rects);
  433. }
  434.  
  435. static void free_bandlist(struct BandList *bl)
  436. {
  437.     free(bl->miny);
  438.     free(bl->maxy);
  439. }
  440.  
  441. static int regionrect_cmpfn(const void *a, const void *b)
  442. {
  443.     struct Rectangle *ra = (struct Rectangle *)a;
  444.     struct Rectangle *rb = (struct Rectangle *)b;
  445.     
  446.     if (ra->MinY < rb->MinY)
  447.     return -1;
  448.     if (ra->MinY > rb->MinY)
  449.     return 1;
  450.     if (ra->MinX < rb->MinX)
  451.     return -1;
  452.     if (ra->MinX > rb->MinX)
  453.     return 1;
  454.     if (ra->MaxX < rb->MaxX)
  455.     return -1;
  456.     return 1;
  457. }
  458.  
  459. static __inline__ int min(int x, int y)
  460. {
  461.     return x < y ? x : y;
  462. }
  463.  
  464. static __inline__ int max(int x, int y)
  465. {
  466.     return x > y ? x : y;
  467. }
  468.  
  469. static void add_rect_to_bands(struct BandList *bl, struct Rectangle *rect)
  470. {
  471.     int j;
  472.     struct Rectangle tmpr = *rect;
  473.     
  474.     for (j = 0; j < bl->count; j++) {
  475.     /* Is the current band before the rectangle? */
  476.     if (bl->maxy[j] < tmpr.MinY)
  477.         continue;
  478.     /* Band already present? */
  479.     if (bl->miny[j] == tmpr.MinY && bl->maxy[j] == tmpr.MaxY)
  480.         break;
  481.     /* Completely new band? Add it */
  482.     if (bl->miny[j] > tmpr.MaxY) {
  483.         add_band(bl, tmpr.MinY, tmpr.MaxY, j);
  484.         break;
  485.     }
  486.     /* Now we know that the bands are overlapping.
  487.      * See whether they match in one point */
  488.     if (bl->miny[j] == tmpr.MinY) {
  489.         int t;
  490.         if (bl->maxy[j] < tmpr.MaxY) {
  491.         /* Rectangle exceeds band */
  492.         tmpr.MinY = bl->maxy[j]+1;
  493.         continue;
  494.         }
  495.         /* Rectangle splits band */
  496.         t = bl->maxy[j];
  497.         bl->maxy[j] = tmpr.MaxY;
  498.         tmpr.MinY = bl->maxy[j] + 1;
  499.         tmpr.MaxY = t;
  500.         continue;
  501.     } else if (bl->maxy[j] == tmpr.MaxY) {
  502.         int t;
  503.         if (bl->miny[j] > tmpr.MinY) {
  504.         /* Rectangle exceeds band */
  505.         t = bl->miny[j];
  506.         bl->miny[j] = tmpr.MinY;
  507.         bl->maxy[j] = t-1;
  508.         tmpr.MinY = t;
  509.         continue;
  510.         }
  511.         /* Rectangle splits band */
  512.         bl->maxy[j] = tmpr.MinY - 1;
  513.         continue;
  514.     }
  515.     /* Bands overlap and match in no points. Get a new band and align */
  516.     if (bl->miny[j] > tmpr.MinY) {
  517.         /* Rectangle begins before band, so make a new band before
  518.          * and adjust rectangle */
  519.         add_band(bl, tmpr.MinY, bl->miny[j] - 1, j);
  520.         tmpr.MinY = bl->miny[j+1];
  521.     } else {
  522.         /* Rectangle begins in band */
  523.         add_band(bl, bl->miny[j], tmpr.MinY - 1, j);
  524.         bl->miny[j+1] = tmpr.MinY;
  525.     }
  526.     continue;
  527.     }
  528.     if (j == bl->count)
  529.     add_band(bl, tmpr.MinY, tmpr.MaxY, j);
  530. }
  531.  
  532. static void region_addbands(struct RectList *rl, struct BandList *bl)
  533. {
  534.     int i,j;
  535.  
  536.     for (i = 0; i < rl->count; i++) {
  537.     add_rect_to_bands(bl, rl->rects + i);
  538.     }
  539. }
  540.  
  541. static void merge_bands(struct BandList *dest, struct BandList *src)
  542. {
  543.     int i;
  544.     for (i = 0; i < src->count; i++) {
  545.     struct Rectangle tmp;
  546.     tmp.MinY = src->miny[i];
  547.     tmp.MaxY = src->maxy[i];
  548.     add_rect_to_bands(dest, &tmp);
  549.     }
  550. }
  551.  
  552. static void region_splitrects_band(struct RectList *rl, struct BandList *bl)
  553. {
  554.     int i,j;
  555.     for (i = 0; i < rl->count; i++) {
  556.     for (j = 0; j < bl->count; j++) {
  557.         if (bl->miny[j] == rl->rects[i].MinY && bl->maxy[j] == rl->rects[i].MaxY)
  558.         break;
  559.         if (rl->rects[i].MinY > bl->maxy[j])
  560.         continue;
  561.         if (bl->miny[j] == rl->rects[i].MinY) {
  562.         struct Rectangle tmpr;
  563.         tmpr.MinX = rl->rects[i].MinX;
  564.         tmpr.MaxX = rl->rects[i].MaxX;
  565.         tmpr.MinY = bl->maxy[j] + 1;
  566.         tmpr.MaxY = rl->rects[i].MaxY;
  567.         add_rect(rl, tmpr); /* will be processed later */
  568.         rl->rects[i].MaxY = bl->maxy[j];
  569.         break;
  570.         }
  571.         fprintf(stderr, "Foo..\n");
  572.     }
  573.     }
  574.     qsort(rl->rects, rl->count, sizeof (struct Rectangle), regionrect_cmpfn);
  575. }
  576.  
  577. static void region_coalesce_rects(struct RectList *rl, int do_2nd_pass)
  578. {
  579.     int i,j;
  580.  
  581.     /* First pass: Coalesce horizontally */
  582.     for (i = j = 0; i < rl->count;) {
  583.     int offs = 1;
  584.     while (i + offs < rl->count) {
  585.         if (rl->rects[i].MinY != rl->rects[i+offs].MinY
  586.         || rl->rects[i].MaxY != rl->rects[i+offs].MaxY
  587.         || rl->rects[i].MaxX+1 < rl->rects[i+offs].MinX)
  588.         break;
  589.         rl->rects[i].MaxX = rl->rects[i+offs].MaxX;
  590.         offs++;
  591.     }
  592.     rl->rects[j++] = rl->rects[i];
  593.     i += offs;
  594.     }
  595.     rl->count = j;
  596.     
  597.     if (!do_2nd_pass)
  598.     return;
  599.     
  600.     /* Second pass: Coalesce bands */
  601.     for (i = 0; i < rl->count;) {
  602.     int match = 0;
  603.     for (j = i + 1; j < rl->count; j++)
  604.         if (rl->rects[i].MinY != rl->rects[j].MinY)
  605.         break;
  606.     if (j < rl->count && rl->rects[i].MaxY + 1 == rl->rects[j].MinY) {
  607.         int k;
  608.         match = 1;
  609.         for (k = 0; i+k < j; k++) {
  610.         if (j+k >= rl->count
  611.             || rl->rects[j+k].MinY != rl->rects[j].MinY)
  612.         {
  613.             match = 0; break;
  614.         }
  615.         if (rl->rects[i+k].MinX != rl->rects[j+k].MinX
  616.             || rl->rects[i+k].MaxX != rl->rects[j+k].MaxX)
  617.         {
  618.             match = 0;
  619.             break;
  620.         }
  621.         }
  622.         if (j+k < rl->count && rl->rects[j+k].MinY == rl->rects[j].MinY)
  623.         match = 0;
  624.         if (match) {
  625.         for (k = 0; i+k < j; k++)
  626.             rl->rects[i+k].MaxY = rl->rects[j].MaxY;
  627.         memmove(rl->rects + j, rl->rects + j + k, (rl->count - j - k)*sizeof(struct Rectangle));
  628.         rl->count -= k;
  629.         }
  630.     }
  631.     if (!match)
  632.         i = j;
  633.     }
  634. }
  635.  
  636. static int copy_rects (uaecptr region, struct RectList *rl)
  637. {
  638.     uaecptr regionrect;
  639.     int numrects = 0;
  640.     struct Rectangle b;
  641.     regionrect = get_long(region+8);
  642.     b.MinX = get_word(region);
  643.     b.MinY = get_word(region+2);
  644.     b.MaxX = get_word(region+4);
  645.     b.MaxY = get_word(region+6);
  646.     
  647.     while (regionrect != 0) {
  648.     struct Rectangle tmpr;
  649.     
  650.     tmpr.MinX = (uae_s16)get_word(regionrect+8)  + b.MinX;
  651.     tmpr.MinY = (uae_s16)get_word(regionrect+10) + b.MinY;
  652.     tmpr.MaxX = (uae_s16)get_word(regionrect+12) + b.MinX;
  653.     tmpr.MaxY = (uae_s16)get_word(regionrect+14) + b.MinY;
  654.     add_rect(rl, tmpr);
  655.     regionrect = get_long(regionrect);
  656.     numrects++;
  657.     }
  658.     return numrects;
  659. }
  660.  
  661. static int rect_in_region(struct RectList *rl, struct Rectangle *r)
  662. {
  663.     int i;
  664.     int miny = r->MinY;
  665.  
  666.     for (i = 0; i < rl->count; i++) {
  667.     int j;
  668.     if (rl->rects[i].MaxY < miny)
  669.         continue;
  670.     if (rl->rects[i].MinY > miny)
  671.         break;
  672.     if (rl->rects[i].MaxX < r->MinX)
  673.         continue;
  674.     if (rl->rects[i].MinX > r->MaxX)
  675.         break;
  676.     /* Overlap! */
  677.     j = i;
  678.     for (;;) {
  679.         if (rl->rects[j].MaxX > r->MaxX) {
  680.         miny = rl->rects[i].MaxY + 1;
  681.         break;
  682.         }
  683.         j++;
  684.         if (j == rl->count)
  685.         break;
  686.         if (rl->rects[j].MinX != rl->rects[j-1].MaxX+1)
  687.         break;
  688.         if (rl->rects[i].MinY != rl->rects[j].MinY)
  689.         break;
  690.     }
  691.     if (miny <= rl->rects[i].MaxY)
  692.         break;
  693.     }
  694.     return 0;
  695. }
  696.  
  697. typedef void (*regionop)(struct RectList *,struct RectList *,struct RectList *);
  698.  
  699. static void region_do_ClearRegionRegion(struct RectList *rl1,struct RectList *rl2,
  700.                     struct RectList *rl3)
  701. {
  702.     int i,j;
  703.  
  704.     for (i = j = 0; i < rl2->count && j < rl1->count;) {
  705.     struct Rectangle tmpr;
  706.  
  707.     while ((rl1->rects[j].MinY < rl2->rects[i].MinY
  708.         || (rl1->rects[j].MinY == rl2->rects[i].MinY
  709.             && rl1->rects[j].MaxX < rl2->rects[i].MinX))
  710.            && j < rl1->count)
  711.         j++;
  712.     if (j >= rl1->count)
  713.         break;
  714.     while ((rl1->rects[j].MinY > rl2->rects[i].MinY
  715.         || (rl1->rects[j].MinY == rl2->rects[i].MinY
  716.             && rl1->rects[j].MinX > rl2->rects[i].MaxX))
  717.            && i < rl2->count)
  718.     {
  719.         add_rect(rl3, rl2->rects[i]);
  720.         i++;
  721.     }
  722.     if (i >= rl2->count)
  723.         break;
  724.     
  725.     tmpr = rl2->rects[i];
  726.     
  727.     while (i < rl2->count && j < rl1->count
  728.            && rl1->rects[j].MinY == tmpr.MinY
  729.            && rl2->rects[i].MinY == tmpr.MinY
  730.            && rl1->rects[j].MinX <= rl2->rects[i].MaxX
  731.            && rl1->rects[j].MaxX >= rl2->rects[i].MinX)
  732.     {
  733.         int oldmin = tmpr.MinX;
  734.         int oldmax = tmpr.MaxX;
  735.         if (tmpr.MinX < rl1->rects[j].MinX) {
  736.         tmpr.MaxX = rl1->rects[j].MinX - 1;
  737.         add_rect(rl3, tmpr);
  738.         }
  739.         if (oldmax <= rl1->rects[j].MaxX) {
  740.         i++;
  741.         if (i < rl2->count && rl2->rects[i].MinY == tmpr.MinY)
  742.             tmpr = rl2->rects[i];
  743.         } else {
  744.         tmpr.MinX = rl1->rects[j].MaxX + 1;
  745.         tmpr.MaxX = oldmax;
  746.         j++;
  747.         }
  748.     }
  749.     }
  750.     for(; i < rl2->count; i++)
  751.     add_rect(rl3, rl2->rects[i]);
  752. }
  753.  
  754. static void region_do_AndRegionRegion(struct RectList *rl1,struct RectList *rl2,
  755.                       struct RectList *rl3)
  756. {
  757.     int i,j;
  758.  
  759.     for (i = j = 0; i < rl2->count && j < rl1->count;) {
  760.     while ((rl1->rects[j].MinY < rl2->rects[i].MinY
  761.         || (rl1->rects[j].MinY == rl2->rects[i].MinY
  762.             && rl1->rects[j].MaxX < rl2->rects[i].MinX))
  763.            && j < rl1->count)
  764.         j++;
  765.     if (j >= rl1->count)
  766.         break;
  767.     while ((rl1->rects[j].MinY > rl2->rects[i].MinY
  768.         || (rl1->rects[j].MinY == rl2->rects[i].MinY
  769.             && rl1->rects[j].MinX > rl2->rects[i].MaxX))
  770.            && i < rl2->count)
  771.         i++;
  772.     if (i >= rl2->count)
  773.         break;
  774.     if (rl1->rects[j].MinY == rl2->rects[i].MinY
  775.         && rl1->rects[j].MinX <= rl2->rects[i].MaxX
  776.         && rl1->rects[j].MaxX >= rl2->rects[i].MinX)
  777.     {
  778.         /* We have an intersection! */
  779.         struct Rectangle tmpr;
  780.         tmpr = rl2->rects[i];
  781.         if (tmpr.MinX < rl1->rects[j].MinX)
  782.         tmpr.MinX = rl1->rects[j].MinX;
  783.         if (tmpr.MaxX > rl1->rects[j].MaxX)
  784.         tmpr.MaxX = rl1->rects[j].MaxX;
  785.         add_rect(rl3, tmpr);
  786.         if (rl1->rects[j].MaxX == rl2->rects[i].MaxX)
  787.         i++, j++;
  788.         else if (rl1->rects[j].MaxX > rl2->rects[i].MaxX)
  789.         i++;
  790.         else
  791.         j++;
  792.     }
  793.     }
  794. }
  795.  
  796. static void region_do_OrRegionRegion(struct RectList *rl1,struct RectList *rl2,
  797.                      struct RectList *rl3)
  798. {
  799.     int i,j;
  800.  
  801.     for (i = j = 0; i < rl2->count && j < rl1->count;) {
  802.     while ((rl1->rects[j].MinY < rl2->rects[i].MinY
  803.         || (rl1->rects[j].MinY == rl2->rects[i].MinY
  804.             && rl1->rects[j].MaxX < rl2->rects[i].MinX))
  805.            && j < rl1->count)
  806.     {
  807.         add_rect(rl3, rl1->rects[j]);
  808.         j++;
  809.     }
  810.     if (j >= rl1->count)
  811.         break;
  812.     while ((rl1->rects[j].MinY > rl2->rects[i].MinY
  813.         || (rl1->rects[j].MinY == rl2->rects[i].MinY
  814.             && rl1->rects[j].MinX > rl2->rects[i].MaxX))
  815.            && i < rl2->count)
  816.     {
  817.         add_rect(rl3, rl2->rects[i]);
  818.         i++;
  819.     }
  820.     if (i >= rl2->count)
  821.         break;
  822.     if (rl1->rects[j].MinY == rl2->rects[i].MinY
  823.         && rl1->rects[j].MinX <= rl2->rects[i].MaxX
  824.         && rl1->rects[j].MaxX >= rl2->rects[i].MinX)
  825.     {
  826.         /* We have an intersection! */
  827.         struct Rectangle tmpr;
  828.         tmpr = rl2->rects[i];
  829.         if (tmpr.MinX > rl1->rects[j].MinX)
  830.         tmpr.MinX = rl1->rects[j].MinX;
  831.         if (tmpr.MaxX < rl1->rects[j].MaxX)
  832.         tmpr.MaxX = rl1->rects[j].MaxX;
  833.         i++; j++;
  834.         for (;;) {
  835.         int cont = 0;
  836.         if (j < rl1->count && rl1->rects[j].MinY == tmpr.MinY
  837.             && tmpr.MaxX+1 >= rl1->rects[j].MinX) {
  838.             if (tmpr.MaxX < rl1->rects[j].MaxX)
  839.             tmpr.MaxX = rl1->rects[j].MaxX;
  840.             j++; cont = 1;
  841.         }
  842.         if (i < rl2->count && rl2->rects[i].MinY == tmpr.MinY
  843.             && tmpr.MaxX+1 >= rl2->rects[i].MinX) {
  844.             if (tmpr.MaxX < rl2->rects[i].MaxX)
  845.             tmpr.MaxX = rl2->rects[i].MaxX;
  846.             i++; cont = 1;
  847.         }
  848.         if (!cont)
  849.             break;
  850.         }
  851.         add_rect(rl3, tmpr);
  852.     }
  853.     }
  854.     for(; i < rl2->count; i++)
  855.     add_rect(rl3, rl2->rects[i]);
  856.     for(; j < rl1->count; j++)
  857.     add_rect(rl3, rl1->rects[j]);
  858. }
  859.  
  860. static void region_do_XorRegionRegion(struct RectList *rl1,struct RectList *rl2,
  861.                       struct RectList *rl3)
  862. {
  863.     int i,j;
  864.  
  865.     for (i = j = 0; i < rl2->count && j < rl1->count;) {
  866.     struct Rectangle tmpr1, tmpr2;
  867.  
  868.     while ((rl1->rects[j].MinY < rl2->rects[i].MinY
  869.         || (rl1->rects[j].MinY == rl2->rects[i].MinY
  870.             && rl1->rects[j].MaxX < rl2->rects[i].MinX))
  871.            && j < rl1->count)
  872.     {
  873.         add_rect(rl3, rl1->rects[j]);
  874.         j++;
  875.     }
  876.     if (j >= rl1->count)
  877.         break;
  878.     while ((rl1->rects[j].MinY > rl2->rects[i].MinY
  879.         || (rl1->rects[j].MinY == rl2->rects[i].MinY
  880.             && rl1->rects[j].MinX > rl2->rects[i].MaxX))
  881.            && i < rl2->count)
  882.     {
  883.         add_rect(rl3, rl2->rects[i]);
  884.         i++;
  885.     }
  886.     if (i >= rl2->count)
  887.         break;
  888.  
  889.     tmpr2 = rl2->rects[i];
  890.     tmpr1 = rl1->rects[j];
  891.     
  892.     while (i < rl2->count && j < rl1->count
  893.            && rl1->rects[j].MinY == tmpr1.MinY
  894.            && rl2->rects[i].MinY == tmpr1.MinY
  895.            && rl1->rects[j].MinX <= rl2->rects[i].MaxX
  896.            && rl1->rects[j].MaxX >= rl2->rects[i].MinX)
  897.     {
  898.         int oldmin2 = tmpr2.MinX;
  899.         int oldmax2 = tmpr2.MaxX;
  900.         int oldmin1 = tmpr1.MinX;
  901.         int oldmax1 = tmpr1.MaxX;
  902.         int need_1 = 0, need_2 = 0;
  903.  
  904.         if (tmpr2.MinX > tmpr1.MinX    && tmpr2.MaxX < tmpr1.MaxX) 
  905.         {
  906.         /*
  907.          *    ###########
  908.          *       ****
  909.          */
  910.         tmpr1.MaxX = tmpr2.MinX - 1;
  911.         add_rect(rl3, tmpr1);
  912.         tmpr1.MaxX = oldmax1;
  913.         tmpr1.MinX = tmpr2.MaxX + 1;
  914.         add_rect(rl3, tmpr1);
  915.         need_2 = 1;
  916.         } else if (tmpr2.MinX > tmpr1.MinX && tmpr2.MaxX > tmpr1.MaxX) {
  917.         /*
  918.          *    ##########
  919.          *       *********
  920.          */
  921.         tmpr1.MaxX = tmpr2.MinX - 1;
  922.         add_rect(rl3, tmpr1);
  923.         tmpr2.MinX = oldmax1 + 1;
  924.         add_rect(rl3, tmpr2);
  925.         need_1 = 1;
  926.         } else if (tmpr2.MinX < tmpr1.MinX && tmpr2.MaxX < tmpr1.MaxX) {
  927.         /*
  928.          *       ##########
  929.          *    *********
  930.          */
  931.         tmpr2.MaxX = tmpr1.MinX - 1;
  932.         add_rect(rl3, tmpr2);
  933.         tmpr1.MinX = oldmax2 + 1;
  934.         add_rect(rl3, tmpr1);
  935.         need_2 = 1;
  936.         } else if (tmpr2.MinX < tmpr1.MinX && tmpr2.MaxX > tmpr1.MaxX) {
  937.         /*
  938.          *       ###
  939.          *    *********
  940.          */
  941.         tmpr2.MaxX = tmpr1.MinX - 1;
  942.         add_rect(rl3, tmpr2);
  943.         tmpr2.MaxX = oldmax2;
  944.         tmpr2.MinX = tmpr1.MaxX + 1;
  945.         add_rect(rl3, tmpr2);
  946.         need_1 = 1;
  947.         } else if (tmpr1.MinX == tmpr2.MinX && tmpr2.MaxX < tmpr1.MaxX) {
  948.         /*
  949.          *    #############
  950.          *    *********
  951.          */
  952.         tmpr1.MinX = tmpr2.MaxX + 1;
  953.         need_2 = 1;
  954.         } else if (tmpr1.MinX == tmpr2.MinX && tmpr2.MaxX > tmpr1.MaxX) {
  955.         /*
  956.          *    #########
  957.          *    *************
  958.          */
  959.         tmpr2.MinX = tmpr1.MaxX + 1;
  960.         need_1 = 1;
  961.         } else if (tmpr1.MinX < tmpr2.MinX && tmpr2.MaxX == tmpr1.MaxX) {
  962.         /*
  963.          *    #############
  964.          *        *********
  965.          */
  966.         tmpr1.MaxX = tmpr2.MinX - 1;
  967.         add_rect(rl3, tmpr1);
  968.         need_2 = need_1 = 1;
  969.         } else if (tmpr1.MinX > tmpr2.MinX && tmpr2.MaxX == tmpr1.MaxX) {
  970.         /*
  971.          *        #########
  972.          *    *************
  973.          */
  974.         tmpr2.MaxX = tmpr1.MinX - 1;
  975.         add_rect(rl3, tmpr2);
  976.         need_2 = need_1 = 1;
  977.         } else {
  978.         assert(tmpr1.MinX == tmpr2.MinX && tmpr2.MaxX == tmpr1.MaxX);
  979.         need_1 = need_2 = 1;
  980.         }
  981.         if (need_1) {
  982.         j++;
  983.         if (j < rl1->count && rl1->rects[j].MinY == tmpr1.MinY)
  984.             tmpr1 = rl1->rects[j];
  985.         }
  986.         if (need_2) {
  987.         i++;
  988.         if (i < rl2->count && rl2->rects[i].MinY == tmpr2.MinY)
  989.             tmpr2 = rl2->rects[i];
  990.         }
  991.     }
  992.     }
  993.     for(; i < rl2->count; i++)
  994.     add_rect(rl3, rl2->rects[i]);
  995.     for(; j < rl1->count; j++)
  996.     add_rect(rl3, rl1->rects[j]);
  997. }
  998.  
  999. static uae_u32 gfxl_perform_regionop(regionop op, int with_rect)
  1000. {
  1001.     int i,j,k;
  1002.     uaecptr reg1;
  1003.     uaecptr reg2;
  1004.     uaecptr tmp, rpp;
  1005.     struct RectList rl1, rl2, rl3;
  1006.     struct BandList bl;
  1007.  
  1008.     int retval = 0;
  1009.     int numrects2;
  1010.     
  1011.     init_rectlist(&rl1); init_rectlist(&rl2); init_rectlist(&rl3);
  1012.  
  1013.     if (with_rect) {
  1014.     struct Rectangle tmpr;
  1015.     reg2 = m68k_areg(regs, 0);
  1016.     numrects2 = copy_rects(reg2, &rl2);
  1017.     tmpr.MinX = get_word(m68k_areg(regs, 1));
  1018.     tmpr.MinY = get_word(m68k_areg(regs, 1) + 2);
  1019.     tmpr.MaxX = get_word(m68k_areg(regs, 1) + 4);
  1020.     tmpr.MaxY = get_word(m68k_areg(regs, 1) + 6);
  1021.     add_rect(&rl1, tmpr);
  1022.     } else {
  1023.     reg1 = m68k_areg(regs, 0);
  1024.     reg2 = m68k_areg(regs, 1);
  1025.  
  1026.     copy_rects(reg1, &rl1);
  1027.     numrects2 = copy_rects(reg2, &rl2);
  1028.     }
  1029.  
  1030.     init_bandlist(&bl);
  1031.     region_addbands(&rl1, &bl);
  1032.     region_addbands(&rl2, &bl);
  1033.     region_splitrects_band(&rl1, &bl);
  1034.     region_splitrects_band(&rl2, &bl);
  1035.     region_coalesce_rects(&rl1, 0);
  1036.     region_coalesce_rects(&rl2, 0);
  1037.  
  1038.     (*op)(&rl1, &rl2, &rl3);
  1039.     region_coalesce_rects(&rl3, 1);
  1040.  
  1041.     rpp = reg2 + 8;
  1042.     if (rl3.count < numrects2) {
  1043.     while (numrects2-- != rl3.count) {
  1044.         tmp = get_long(rpp);
  1045.         put_long(rpp, get_long(tmp));
  1046.         amiga_free(tmp, 16);
  1047.     }
  1048.     if (rl3.count > 0)
  1049.         put_long(get_long(rpp) + 4, rpp);
  1050.     } else if (rl3.count > numrects2) {
  1051.     while(numrects2++ != rl3.count) {
  1052.         uaecptr prev = get_long(rpp);
  1053.         tmp = amiga_malloc(16);
  1054.         if (tmp == 0)
  1055.         goto done;
  1056.         put_long(tmp, prev);
  1057.         put_long(tmp + 4, rpp);
  1058.         if (prev != 0)
  1059.         put_long(prev + 4, tmp);
  1060.         put_long(rpp, tmp);        
  1061.     }
  1062.     }
  1063.     
  1064.     if (rl3.count > 0) {
  1065.     rpp = reg2 + 8;
  1066.     for (i = 0; i < rl3.count; i++) {
  1067.         uaecptr rr = get_long(rpp);
  1068.         put_word(rr+8, rl3.rects[i].MinX - rl3.bounds.MinX);
  1069.         put_word(rr+10, rl3.rects[i].MinY - rl3.bounds.MinY);
  1070.         put_word(rr+12, rl3.rects[i].MaxX - rl3.bounds.MinX);
  1071.         put_word(rr+14, rl3.rects[i].MaxY - rl3.bounds.MinY);
  1072.         rpp = rr;
  1073.     }
  1074.     if (get_long(rpp) != 0)
  1075.         fprintf(stderr, "BUG\n");
  1076.     } 
  1077.     put_word(reg2+0, rl3.bounds.MinX);
  1078.     put_word(reg2+2, rl3.bounds.MinY);
  1079.     put_word(reg2+4, rl3.bounds.MaxX);
  1080.     put_word(reg2+6, rl3.bounds.MaxY);
  1081.     retval = 1;
  1082.  
  1083.     done:
  1084.     free_rectlist(&rl1); free_rectlist(&rl2); free_rectlist(&rl3);
  1085.     free_bandlist(&bl);    
  1086.  
  1087.     return retval;
  1088. }
  1089.  
  1090. static uae_u32 gfxl_AndRegionRegion(void)
  1091. {
  1092.     return gfxl_perform_regionop(region_do_AndRegionRegion, 0);
  1093. }
  1094. static uae_u32 gfxl_XorRegionRegion(void)
  1095. {
  1096.     return gfxl_perform_regionop(region_do_XorRegionRegion, 0);
  1097. }
  1098. static uae_u32 gfxl_OrRegionRegion(void)
  1099. {
  1100.     return gfxl_perform_regionop(region_do_OrRegionRegion, 0);
  1101. }
  1102.  
  1103. static uae_u32 gfxl_ClearRectRegion(void)
  1104. {
  1105.     return gfxl_perform_regionop(region_do_ClearRegionRegion, 1);
  1106. }
  1107. static uae_u32 gfxl_OrRectRegion(void)
  1108. {
  1109.     return gfxl_perform_regionop(region_do_OrRegionRegion, 1);
  1110. }
  1111.  
  1112. static uae_u32 gfxl_AndRectRegion(void)
  1113. {
  1114.     return gfxl_perform_regionop(region_do_AndRegionRegion, 1);
  1115. }
  1116.  
  1117. static uae_u32 gfxl_XorRectRegion(void)
  1118. {
  1119.     return gfxl_perform_regionop(region_do_XorRegionRegion, 1);
  1120. }
  1121.  
  1122.  
  1123. /* Layers code */
  1124.  
  1125. static void LY_LockLayer(uaecptr layer)
  1126. {
  1127.     uaecptr sigsem = layer + 72;
  1128.  
  1129.     m68k_areg(regs, 0) = sigsem;
  1130.     CallLib(get_long(4), -564);
  1131. }
  1132.  
  1133. static void LY_UnlockLayer(uaecptr layer)
  1134. {
  1135.     uaecptr sigsem = layer + 72;
  1136.  
  1137.     m68k_areg(regs, 0) = sigsem;
  1138.     CallLib(get_long(4), -570);
  1139. }
  1140.  
  1141. static void LY_LockLayerInfo(uaecptr li)
  1142. {
  1143.     uaecptr sigsem = li + 24;
  1144.  
  1145.     m68k_areg(regs, 0) = sigsem;
  1146.     CallLib(get_long(4), -564);
  1147.     put_byte(li+91, get_byte(li+91)+1);
  1148. }
  1149.  
  1150. static void LY_UnlockLayerInfo(uaecptr li)
  1151. {
  1152.     uaecptr sigsem = li + 24;
  1153.  
  1154.     put_byte(li+91, get_byte(li+91)-1);
  1155.     m68k_areg(regs, 0) = sigsem;
  1156.     CallLib(get_long(4), -570);
  1157. }
  1158.  
  1159. static void LY_LockLayers(uaecptr li)
  1160. {
  1161.     uaecptr l = get_long (li);
  1162.     LY_LockLayerInfo(li);
  1163.     while (l != 0) {
  1164.     LY_LockLayer(l);
  1165.     l = get_long(l);
  1166.     }
  1167.     LY_UnlockLayerInfo(li);
  1168. }
  1169.  
  1170. static void LY_UnlockLayers(uaecptr li)
  1171. {
  1172.     uaecptr l = get_long (li);
  1173.     LY_LockLayerInfo(li);
  1174.     while (l != 0) {
  1175.     LY_UnlockLayer(l);
  1176.     l = get_long(l);
  1177.     }
  1178.     LY_UnlockLayerInfo(li);
  1179. }
  1180.  
  1181. #define LAYER_CLUELESS   0x8000 /* Indicates we know nothing about the layer's regions. */
  1182. #define LAYER_CR_CHANGED 0x4000 /* Indicates that the cliprects in Amiga memory need to be re-done */
  1183. #define LAYER_REDO       0x2000 /* Indicates that we have regions, but they are bogus. */
  1184.  
  1185. static uae_u32 layer_uniq = 1;
  1186.  
  1187. struct MyLayerInfo {
  1188.     struct uniq_head head;
  1189.     uaecptr amigaos_linfo;
  1190.     uniq_list layer_list;
  1191. };
  1192.  
  1193. struct MyLayer {
  1194.     struct uniq_head head;
  1195.     uaecptr amigaos_layer, rastport;
  1196.     struct Rectangle bounds;
  1197.     struct RectList clipregion;
  1198.     struct RectList obscured;
  1199.     struct RectList visible;
  1200.     struct BandList big_bands; /* created by obscuring layers */
  1201.     struct BandList small_bands; /* big_bands + those from clipregion */
  1202.     struct RectList damage;
  1203.     struct BandList damage_bands;
  1204.     struct MyLayerInfo *mli;
  1205. };
  1206.  
  1207. static uniq_list MyLayerInfo_list = UNIQ_INIT;
  1208.  
  1209. static void LY_InitLayers(uaecptr li)
  1210. {
  1211.     memset (get_real_address(li), 0, 92);
  1212.     put_long(li + 0, 0); /* top layer */
  1213.     put_long(li+84, 0); /* uniq: */
  1214.     m68k_areg(regs, 0) = li + 24; CallLib(get_long(4), -558); /* InitSemaphore() */
  1215.     put_word(li+88, 0); /* flags (???) */
  1216.     put_byte(li+89, 0); /* fatten_count */
  1217.     /* @@@ How big can I assume the structure? What's all this 1.0/1.1 cruft? */
  1218. }
  1219.  
  1220. static void LY_FattenLayerInfo(uaecptr li)
  1221. {
  1222.     struct MyLayerInfo *mli;
  1223.     int fatten_count = get_byte (li + 89);
  1224.     if (fatten_count == 0) {
  1225.     mli = (struct MyLayerInfo *)malloc(sizeof(struct MyLayerInfo));
  1226.     add_uniq(&MyLayerInfo_list, &mli->head, li + 84);
  1227.     init_uniq(&mli->layer_list);
  1228.     mli->amigaos_linfo = li;
  1229.     }
  1230.     put_byte (li + 89, fatten_count + 1);
  1231. }
  1232.  
  1233. static void LY_ThinLayerInfo(uaecptr li)
  1234. {
  1235.     int fatten_count = get_byte (li + 89)-1;
  1236.     put_byte (li + 89, fatten_count);
  1237.     if (fatten_count == 0) {
  1238.     struct MyLayerInfo *mli = (struct MyLayerInfo *)find_and_rem_uniq(&MyLayerInfo_list, get_long(li+84));
  1239.     if (mli)
  1240.         free(mli);
  1241.     }
  1242. }
  1243.  
  1244. static void build_cliprect (struct MyLayer *l, struct Rectangle *bounds,
  1245.                 int obscured, uaecptr *crp, uaecptr *prev)
  1246. {
  1247.     uaecptr cr = get_long (*crp);
  1248.     if (cr == 0) {
  1249.     put_long (*crp, cr = amiga_malloc(CLIPRECT_SIZE));
  1250.     put_long (cr, 0);
  1251.     }
  1252.     *prev = cr;
  1253.     *crp = cr;
  1254.     put_word (cr + 16, bounds->MinX);
  1255.     put_word (cr + 18, bounds->MinY);
  1256.     put_word (cr + 20, bounds->MaxX);
  1257.     put_word (cr + 22, bounds->MaxY);
  1258.     put_long (cr + 8, obscured ? l->amigaos_layer : 0); /* cheat */
  1259.     put_long (cr + 12, 0); /* no smart refresh yet */
  1260. }
  1261.  
  1262. static void build_cliprects (struct MyLayer *l)
  1263. {
  1264.     uaecptr layer = l->amigaos_layer;
  1265.     uaecptr cr = layer + 8;
  1266.     uaecptr prev = 0;
  1267.     uae_u16 flags = get_word(layer + 30);
  1268.     int i;
  1269.  
  1270.     if ((flags & LAYER_CR_CHANGED) == 0)
  1271.     return;
  1272.     put_word (layer + 30, flags & ~LAYER_CR_CHANGED);
  1273.     for (i = 0; i < l->obscured.count; i++) {
  1274.     build_cliprect (l, l->obscured.rects + i, 1, &cr, &prev);
  1275.     }
  1276.     for (i = 0; i < l->visible.count; i++) {
  1277.     build_cliprect (l, l->visible.rects + i, 1, &cr, &prev);
  1278.     }
  1279.     while ((prev = get_long (cr))) {
  1280.     put_long (cr, get_long (prev));
  1281.     amiga_free (prev, CLIPRECT_SIZE);
  1282.     }
  1283. }
  1284.  
  1285. static void propagate_clueless_redo (struct MyLayerInfo *mli)
  1286. {
  1287.     /* For all CLUELESS layers, set the REDO bit for all layers below it that overlap it
  1288.      * and delete the data associated with them. */
  1289.     uaecptr current_l = get_long(mli->amigaos_linfo);
  1290.     while (current_l) {
  1291.     struct MyLayer *l = (struct MyLayer *)find_uniq(&mli->layer_list, get_long(current_l + 24));
  1292.     if ((get_word(l->amigaos_layer + 32) & LAYER_CLUELESS) != 0) {
  1293.         uaecptr next_l = get_long(current_l);
  1294.         put_word(l->amigaos_layer + 32, get_word(l->amigaos_layer + 32) | LAYER_REDO);
  1295.         while (next_l) {
  1296.         struct MyLayer *l2 = (struct MyLayer *)find_uniq(&mli->layer_list, get_long(next_l + 24));
  1297.         uae_u16 flags = get_word(l2->amigaos_layer + 32);
  1298.         if (l2->bounds.MinX <= l->bounds.MaxX && l->bounds.MinX <= l2->bounds.MaxX
  1299.             && l2->bounds.MinY <= l->bounds.MaxY && l->bounds.MinY <= l2->bounds.MaxY)
  1300.             put_word(l2->amigaos_layer + 32, flags | LAYER_REDO);
  1301.         if ((flags & (LAYER_REDO|LAYER_CLUELESS)) == 0) {
  1302.             free_rectlist(&l->obscured);
  1303.             free_rectlist(&l->visible);
  1304.             free_bandlist(&l->big_bands);
  1305.             free_bandlist(&l->small_bands);
  1306.         }
  1307.         next_l = get_long(next_l);
  1308.         }
  1309.     }
  1310.     current_l = get_long(current_l);
  1311.     }
  1312. }
  1313.  
  1314. static void redo_layers(struct MyLayerInfo *mli, uaecptr bm)
  1315. {
  1316.     uaecptr current_l;
  1317.     struct RectList tmp_rl;
  1318.  
  1319.     propagate_clueless_redo(mli);
  1320.     current_l = get_long(mli->amigaos_linfo);
  1321.  
  1322.     while (current_l) {
  1323.     struct MyLayer *l = (struct MyLayer *)find_uniq(&mli->layer_list, get_long(current_l + 24));
  1324.     uae_u16 flags = get_word(l->amigaos_layer + 32);
  1325.     if ((flags & LAYER_REDO) != 0) {
  1326.         uaecptr next_l = get_long(current_l+4);
  1327.         int have_rects = 0;
  1328.  
  1329.         init_rectlist(&l->obscured);
  1330.         init_bandlist(&l->big_bands);
  1331.         add_rect_to_bands(&l->big_bands, &l->bounds);
  1332.  
  1333.         while (next_l) {
  1334.         struct MyLayer *l2 = (struct MyLayer *)find_uniq(&mli->layer_list, get_long(next_l + 24));
  1335.         if (l2->visible.bounds.MinX <= l->bounds.MaxX && l->bounds.MinX <= l2->visible.bounds.MaxX
  1336.             && l2->visible.bounds.MinY <= l->bounds.MaxY && l->bounds.MinY <= l2->visible.bounds.MaxY
  1337.             && !rect_in_region (&l->obscured, &l2->visible.bounds))
  1338.         {
  1339.             add_rect_to_bands(&l->big_bands, &l2->visible.bounds);
  1340.             add_rect(&l->obscured, l2->visible.bounds);
  1341.             have_rects++;
  1342.         }
  1343.         next_l = get_long(next_l+4);
  1344.         }
  1345.         init_rectlist(&l->visible);
  1346.         init_rectlist(&tmp_rl);
  1347.         add_rect (&tmp_rl, l->bounds);
  1348.  
  1349.         region_splitrects_band(&l->obscured, &l->big_bands);
  1350.         region_splitrects_band(&tmp_rl, &l->big_bands);
  1351.         region_do_ClearRegionRegion(&l->obscured, &tmp_rl, &l->visible);
  1352.         flags |= LAYER_CR_CHANGED;
  1353.     }
  1354.     put_word (l->amigaos_layer + 32, flags & ~(LAYER_CLUELESS|LAYER_REDO));
  1355.     current_l = get_long(current_l);
  1356.     }
  1357. }
  1358.  
  1359. static struct MyLayer *LY_NewLayer(struct MyLayerInfo *mli, int x0, int x1, int y0, int y1,
  1360.                    uae_u16 flags, uaecptr bm, uaecptr sbm)
  1361. {
  1362.     struct MyLayer *l = (struct MyLayer *)malloc(sizeof (struct MyLayer));
  1363.     uaecptr layer = amiga_malloc(LAYER_SIZE);
  1364.     memset (get_real_address(layer), 0, LAYER_SIZE);
  1365.     l->amigaos_layer = layer;
  1366.     
  1367.     put_word(layer + 16, x0); /* bounds */
  1368.     put_word(layer + 18, y0);
  1369.     put_word(layer + 20, x1);
  1370.     put_word(layer + 22, y1);
  1371.     put_word(layer + 30, flags | LAYER_CLUELESS);
  1372.     put_long(layer + 32, flags & 4 ? sbm : 0); /* ClipRect */
  1373.     put_long(layer + 68, mli->amigaos_linfo);
  1374.     m68k_areg(regs, 0) = layer + 72; CallLib(get_long(4), -558); /* InitSemaphore() */
  1375.     add_uniq(&mli->layer_list, &l->head, layer + 24);
  1376.     l->mli = mli;
  1377.  
  1378.     l->bounds.MinX = x0;
  1379.     l->bounds.MaxX = x1;
  1380.     l->bounds.MinY = y0;
  1381.     l->bounds.MaxY = y1;
  1382.     return l;
  1383. }
  1384.  
  1385. static void LY_DeleteLayer(uaecptr layer)
  1386. {
  1387.     uaecptr cr;
  1388.     struct MyLayer *l = (struct MyLayer *)find_and_rem_uniq(&l->mli->layer_list, get_long (layer + 24));
  1389.     /* Free ClipRects */
  1390.     while ((cr = get_long (l->amigaos_layer + 8))) {
  1391.     put_long (l->amigaos_layer + 8, get_long(cr));
  1392.     amiga_free(cr, CLIPRECT_SIZE);
  1393.     }
  1394.     amiga_free (l->amigaos_layer, LAYER_SIZE);
  1395.     free(l);
  1396. }
  1397.  
  1398. static uaecptr find_behindlayer_position(uaecptr li, uae_u16 flags)
  1399. {
  1400.     uaecptr where = li;
  1401.     for (;;) {
  1402.     uaecptr other = get_long (where);
  1403.     /* End of list? */
  1404.     if (other == 0)
  1405.         break;
  1406.     /* Backdrop? */
  1407.     if ((get_word(other + 30) & 0x40) > (flags & 0x40))
  1408.         break;
  1409.     where = other;
  1410.     }
  1411.     return where;
  1412. }
  1413.  
  1414. static uaecptr LY_CreateLayer(uaecptr li, int x0, int x1, int y0, int y1,
  1415.                   uae_u16 flags, uaecptr bm, uaecptr sbm, uaecptr where)
  1416. {
  1417.     struct MyLayerInfo *mli = (struct MyLayerInfo *)find_uniq(&MyLayerInfo_list, get_long (li + 84));
  1418.     struct MyLayer *l;
  1419.  
  1420.     LY_LockLayerInfo(li);
  1421.     
  1422.     l = LY_NewLayer(mli, x0, x1, y0, y1, flags, bm, sbm);
  1423.     /* Chain into list */
  1424.     put_long(l->amigaos_layer, get_long (where));
  1425.     put_long(l->amigaos_layer + 4, where == li ? 0 : where);
  1426.     if (get_long (where) != 0)
  1427.     put_long(get_long (where) + 4, l->amigaos_layer);
  1428.     put_long(where, l->amigaos_layer);
  1429.     redo_layers(mli, bm);
  1430.     build_cliprects(l);
  1431.     LY_UnlockLayerInfo(li);
  1432.     return l->amigaos_layer;
  1433. }
  1434.  
  1435. static void LY_DisposeLayerInfo(uaecptr li)
  1436. {
  1437.     LY_ThinLayerInfo(li);
  1438.     amiga_free(li, LINFO_SIZE);
  1439. }
  1440.  
  1441. static uae_u32 layers_NewLayerInfo(void)
  1442. {
  1443.     uaecptr li = amiga_malloc(LINFO_SIZE);
  1444.     LY_InitLayers(li);
  1445.     LY_FattenLayerInfo(li);
  1446.     return li;
  1447. }
  1448. static uae_u32 layers_InitLayers(void) { LY_InitLayers (m68k_areg (regs, 0)); return 0; }
  1449. static uae_u32 layers_DisposeLayerInfo(void) { LY_DisposeLayerInfo (m68k_areg (regs, 0)); return 0; }
  1450.  
  1451. static uae_u32 layers_FattenLayerInfo(void) { LY_FattenLayerInfo(m68k_areg(regs, 0)); return 0; }
  1452. static uae_u32 layers_ThinLayerInfo(void) { LY_ThinLayerInfo(m68k_areg(regs, 0)); return 0; }
  1453.  
  1454. static uae_u32 layers_CreateUpfrontLayer(void)
  1455. {
  1456.     return LY_CreateLayer(m68k_areg(regs, 0), (uae_s32)m68k_dreg(regs, 0),
  1457.               (uae_s32)m68k_dreg(regs, 1), (uae_s32)m68k_dreg(regs, 2),
  1458.               (uae_s32)m68k_dreg(regs, 3),
  1459.               m68k_dreg(regs, 4),
  1460.               m68k_areg(regs, 1), m68k_areg(regs, 2), m68k_areg(regs, 0));
  1461. }
  1462. static uae_u32 layers_CreateBehindLayer(void)
  1463. {
  1464.     return LY_CreateLayer(m68k_areg(regs, 0), (uae_s32)m68k_dreg(regs, 0),
  1465.               (uae_s32)m68k_dreg(regs, 1), (uae_s32)m68k_dreg(regs, 2),
  1466.               (uae_s32)m68k_dreg(regs, 3),
  1467.               m68k_dreg(regs, 4),
  1468.               m68k_areg(regs, 1), m68k_areg(regs, 2), 
  1469.               find_behindlayer_position (m68k_areg(regs, 0), m68k_dreg(regs, 4)));
  1470. }
  1471. static uae_u32 layers_DeleteLayer(void) { LY_DeleteLayer (m68k_areg (regs, 1)); return 0; }
  1472.  
  1473. static uae_u32 layers_LockLayer(void)
  1474. {
  1475.     uaecptr layer = m68k_areg(regs, 1);
  1476.     uaecptr li = get_long (layer + 68);
  1477.     struct MyLayerInfo *mli = (struct MyLayerInfo *)find_uniq (&MyLayerInfo_list, get_long (li + 84));
  1478.     struct MyLayer *l = (struct MyLayer *)find_uniq (&mli->layer_list, get_long (layer + 24));
  1479.  
  1480.     LY_LockLayer(layer);
  1481.     build_cliprects (l);
  1482.     return 0;
  1483. }
  1484. static uae_u32 layers_LockLayers(void) { LY_LockLayers(m68k_areg(regs, 0)); return 0; }
  1485. static uae_u32 layers_LockLayerInfo(void) { LY_LockLayerInfo(m68k_areg(regs, 0)); return 0; }
  1486. static uae_u32 layers_UnlockLayer(void) { LY_UnlockLayer(m68k_areg(regs, 0)); return 0; }
  1487. static uae_u32 layers_UnlockLayers(void) { LY_UnlockLayers(m68k_areg(regs, 0)); return 0; }
  1488. static uae_u32 layers_UnlockLayerInfo(void) { LY_UnlockLayerInfo(m68k_areg(regs, 0)); return 0; }
  1489.  
  1490. static uae_u32 layers_ScrollLayer(void)
  1491. {
  1492.     abort();
  1493. }
  1494.  
  1495. static uae_u32 layers_SizeLayer(void)
  1496. {
  1497.     abort();
  1498. }
  1499.  
  1500. static uae_u32 layers_MoveLayer(void)
  1501. {
  1502.     abort();
  1503. }
  1504.  
  1505. static uae_u32 layers_UpfrontLayer(void)
  1506. {
  1507.     abort();
  1508. }
  1509.  
  1510. static uae_u32 layers_BehindLayer(void)
  1511. {
  1512.     abort();
  1513. }
  1514.  
  1515. static uae_u32 layers_MoveLayerInFrontOf(void)
  1516. {
  1517.     abort();
  1518. }
  1519.  
  1520. static uae_u32 layers_BeginUpdate(void)
  1521. {
  1522.     return 1;
  1523. }
  1524.  
  1525. static uae_u32 layers_EndUpdate(void)
  1526. {
  1527.     return 0;
  1528. }
  1529.  
  1530. static uae_u32 layers_WhichLayer(void)
  1531. {
  1532.     abort();
  1533. }
  1534.  
  1535. static uae_u32 layers_InstallClipRegion(void)
  1536. {
  1537.     return 0;
  1538. }
  1539.  
  1540. static uae_u32 layers_SwapBitsRastPortClipRect(void)
  1541. {
  1542.     abort();
  1543. }
  1544.  
  1545. /*
  1546.  *  Initialization
  1547.  */
  1548. static uae_u32 gfxlib_init(void)
  1549. {
  1550.     uae_u32 old_arr;
  1551.     uaecptr sysbase=m68k_areg(regs, 6); 
  1552.     int i=0;
  1553.  
  1554.     /* Install new routines */
  1555.     m68k_dreg(regs, 0)=0;
  1556.     m68k_areg(regs, 1)=gfxlibname;
  1557.     gfxbase=CallLib(sysbase, -408);  /* OpenLibrary */
  1558.     m68k_dreg(regs, 0)=0;
  1559.     m68k_areg(regs, 1)=layerslibname;
  1560.     layersbase=CallLib(sysbase, -408);  /* OpenLibrary */
  1561.  
  1562.     libemu_InstallFunctionFlags(gfxl_WritePixel, gfxbase, -324, TRAPFLAG_EXTRA_STACK, "");
  1563.     libemu_InstallFunctionFlags(gfxl_BltClear, gfxbase, -300, 0, "");
  1564.     libemu_InstallFunctionFlags(gfxl_AndRegionRegion, gfxbase, -624, TRAPFLAG_EXTRA_STACK, "");
  1565.     libemu_InstallFunctionFlags(gfxl_OrRegionRegion, gfxbase, -612, TRAPFLAG_EXTRA_STACK, "");
  1566.     libemu_InstallFunctionFlags(gfxl_XorRegionRegion, gfxbase, -618, TRAPFLAG_EXTRA_STACK, "");
  1567.     libemu_InstallFunctionFlags(gfxl_AndRectRegion, gfxbase, -504, TRAPFLAG_EXTRA_STACK, "");
  1568.     libemu_InstallFunctionFlags(gfxl_OrRectRegion, gfxbase, -510, TRAPFLAG_EXTRA_STACK, "");
  1569.     libemu_InstallFunctionFlags(gfxl_XorRectRegion, gfxbase, -558, TRAPFLAG_EXTRA_STACK, "");
  1570.     libemu_InstallFunctionFlags(gfxl_ClearRectRegion, gfxbase, -522, TRAPFLAG_EXTRA_STACK, "");
  1571.  
  1572. #if 0
  1573. #define MAYBE_FUNCTION(a) NULL
  1574. #else
  1575. #define MAYBE_FUNCTION(a) (a)
  1576. #endif
  1577. #if 0
  1578.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_InitLayers), layersbase, -30, TRAPFLAG_EXTRA_STACK, "InitLayers");
  1579.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_CreateUpfrontLayer), layersbase, -36, TRAPFLAG_EXTRA_STACK, "CreateUpfrontLayer");
  1580.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_CreateBehindLayer), layersbase, -42, TRAPFLAG_EXTRA_STACK, "CreateBehindLayer");
  1581.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_UpfrontLayer), layersbase, -48, TRAPFLAG_EXTRA_STACK, "UpfrontLayer");
  1582.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_BehindLayer), layersbase, -54, TRAPFLAG_EXTRA_STACK, "BehindLayer");
  1583.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_MoveLayer), layersbase, -60, TRAPFLAG_EXTRA_STACK, "MoveLayer");
  1584.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_SizeLayer), layersbase, -66, TRAPFLAG_EXTRA_STACK, "SizeLayer");
  1585.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_ScrollLayer), layersbase, -72, TRAPFLAG_EXTRA_STACK, "ScrollLayer");
  1586.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_BeginUpdate), layersbase, -78, TRAPFLAG_EXTRA_STACK, "BeginUpdate");
  1587.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_EndUpdate), layersbase, -84, TRAPFLAG_EXTRA_STACK, "EndUpdate");
  1588.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_DeleteLayer), layersbase, -90, TRAPFLAG_EXTRA_STACK, "DeleteLayer");
  1589.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_LockLayer), layersbase, -96, TRAPFLAG_EXTRA_STACK, "LockLayer");
  1590.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_UnlockLayer), layersbase, -102, TRAPFLAG_EXTRA_STACK, "UnlockLayer");
  1591.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_LockLayers), layersbase, -108, TRAPFLAG_EXTRA_STACK, "LockLayers");
  1592.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_UnlockLayers), layersbase, -114, TRAPFLAG_EXTRA_STACK, "UnlockLayers");
  1593.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_LockLayerInfo), layersbase, -120, TRAPFLAG_EXTRA_STACK, "LockLayerInfo");
  1594.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_SwapBitsRastPortClipRect), layersbase, -126, TRAPFLAG_EXTRA_STACK, "SwapBitsRastPortClipRect");
  1595.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_WhichLayer), layersbase, -132, TRAPFLAG_EXTRA_STACK, "WhichLayer");
  1596.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_UnlockLayerInfo), layersbase, -138, TRAPFLAG_EXTRA_STACK, "UnlockLayerInfo");
  1597.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_NewLayerInfo), layersbase, -144, TRAPFLAG_EXTRA_STACK, "NewLayerInfo");
  1598.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_DisposeLayerInfo), layersbase, -150, TRAPFLAG_EXTRA_STACK, "DisposeLayerInfo");
  1599.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_FattenLayerInfo), layersbase, -156, TRAPFLAG_EXTRA_STACK, "FattenLayerInfo");
  1600.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_ThinLayerInfo), layersbase, -162, TRAPFLAG_EXTRA_STACK, "ThinLayerInfo");
  1601.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_MoveLayerInFrontOf), layersbase, -168, TRAPFLAG_EXTRA_STACK, "MoveLayerInFrontOf");
  1602.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_InstallClipRegion), layersbase, -174, TRAPFLAG_EXTRA_STACK, "InstallClipRegion");
  1603. #if 0
  1604.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_), layersbase, -180, TRAPFLAG_EXTRA_STACK, "MoveSizeLayer");
  1605.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_), layersbase, -186, TRAPFLAG_EXTRA_STACK, "CreateUpfrontHookLayer");
  1606.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_), layersbase, -192, TRAPFLAG_EXTRA_STACK, "CreateBehindHookLayer");
  1607.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_), layersbase, -198, TRAPFLAG_EXTRA_STACK, "InstallLayerHook");
  1608. #endif
  1609. #endif
  1610.     return 0;
  1611. }
  1612.  
  1613. /* 
  1614.  *  Install the gfx-library-replacement 
  1615.  */
  1616. void gfxlib_install(void)
  1617. {
  1618.     uae_u32 begin, end, resname, resid;
  1619.     int i;
  1620.     
  1621.     if(!use_gfxlib) return;
  1622.     
  1623.     fprintf(stderr, "Warning: you enabled the graphics.library replacement with -g\n"
  1624.         "This may be buggy right now, and will not speed things up much.\n");
  1625.  
  1626.     resname = ds("UAEgfxlib.resource");
  1627.     resid = ds("UAE gfxlib 0.1");
  1628.  
  1629.     gfxlibname = ds("graphics.library");
  1630.     layerslibname = ds("layers.library");
  1631.  
  1632.     begin = here();
  1633.     dw(0x4AFC);             /* RTC_MATCHuae_s16 */
  1634.     dl(begin);              /* our start address */
  1635.     dl(0);                  /* Continue scan here */
  1636.     dw(0x0101);             /* RTF_COLDSTART; Version 1 */
  1637.     dw(0x0805);             /* NT_RESOURCE; pri 5 */
  1638.     dl(resname);            /* name */
  1639.     dl(resid);              /* ID */
  1640.     dl(here() + 4);         /* Init area: directly after this */
  1641.  
  1642.     calltrap(deftrap2(gfxlib_init, TRAPFLAG_EXTRA_STACK, "")); dw(RTS);
  1643.  
  1644.     end = here();
  1645.     org(begin + 6);
  1646.     dl(end);
  1647.  
  1648.     org(end);
  1649. }
  1650. #else
  1651.  
  1652. void gfxlib_install (void)
  1653. {
  1654. }
  1655.  
  1656. #endif
  1657.